package com.insight.modules.util;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;
import java.util.Random;

/**
 * @author 徐庆魁
 * @site www.zhijiapay.com
 * @company 山东智加信息科技有限公司
 * @create 2019-11-04 11:48
 */


public class KeyUtil {
    /**
     * 密钥表
     */
    private static String[] key = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c",
            "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
            "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H",
            "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
    // 密匙（测试专用）
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final String ALGORITHM = "AES";
    private static final String CHARSET = "utf-8";

    private static final String TOKENKEY = "45bPFDTM9LEDGAanGOc+y+7mskjtFCAQHNWAVnUMmmI=";
    /**
     * 建议为16位或32位
     */
    /**
     *  测试使用
     */
    // private static final String KEY = "LiuKeyingshandon";
    /**
     * 生产使用
     */
    private static final String KEY = "sDzj920505LkyYc9";
    /**
     * 必须16位
     * 初始化向量IV不可以为32位，否则异常java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
     */
    /**
     * 测试使用
     */
    // private static final String IV = "20181212sdzjxinx";

    /**
     * 生产使用
     */
    private static final String IV = "20200101SdzjZZL1";

    /**
     * 随机生成加密码AES
     *
     * @return
     * @throws Exception
     */
    public static String theKey() {
        // 使用 SecureRandom 替代 Random，确保随机性不可预测
        SecureRandom secureRandom = new SecureRandom();
        int n = 16;
        String[] ranKey = new String[n];

        // 假设 key 是一个已定义的字符串数组（如字符字典）
        for (int i = 0; i < n; i++) {
            ranKey[i] = key[secureRandom.nextInt(key.length)];
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < ranKey.length; i++) {
            sb.append(ranKey[i]);
        }

        return sb.toString();
    }

    /**
     * 加密
     *
     * @return
     */
    public static String encrypt(String stn) {
        //  String stn = KeyUtil.theKey();
        //  System.out.println(stn);
        try {
            if (StringUtils.isEmpty(stn)) {
                return null;
            }
            byte[] decode = stn.getBytes(CHARSET);
            if (decode == null) {
                return null;
            }
            byte[] bytes = createKeyAndIv(decode, Cipher.ENCRYPT_MODE);
            if (bytes == null) {
                return null;
            }
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     *
     * @param context
     * @return
     */
    public static String decrypt(String context) {
        try {
            if (StringUtils.isEmpty(context)) {
                return null;
            }
            Base64.Decoder decoder = Base64.getDecoder();
            byte[] decode = decoder.decode(context);
            if (decode == null) {
                return null;
            }
            byte[] bytes = createKeyAndIv(decode, Cipher.DECRYPT_MODE);
            if (bytes == null) {
                return null;
            }
            return new String(bytes, CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取key & iv
     *
     * @param context
     * @param opmode
     * @return
     * @throws Exception
     */
    public static byte[] createKeyAndIv(byte[] context, int opmode) throws UnsupportedEncodingException {
        byte[] key = KEY.getBytes(CHARSET);
        byte[] iv = IV.getBytes(CHARSET);
        try {
            return cipherFilter(context, opmode, key, iv);
        } catch (Exception e) {
            throw new IllegalStateException("加密/解密操作失败：系统错误", e);
        }
    }

    /**
     * 执行操作
     *
     * @param context
     * @param opmode
     * @param key
     * @param iv
     * @return
     * @throws Exception
     */
    public static byte[] cipherFilter(byte[] context, int opmode, byte[] key, byte[] iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Key secretKeySpec = new SecretKeySpec(key, ALGORITHM);
        AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(opmode, secretKeySpec, ivParameterSpec);
        return cipher.doFinal(context);
    }

    /**
     * @功能: BCD码转为10进制串(阿拉伯数据)
     * @参数: BCD码
     * @结果: 10进制串
     */
    public static String bcd2Str(byte[] bytes) {
        //StringBuilder temp = new StringBuilder(bytes.length * 2);
        byte temp[] = new byte[bytes.length * 2];
        byte btemp;
        for (int i = 0; i < bytes.length; i++) {
            btemp = (byte) ((bytes[i] & 0xf0) >> 4);
            temp[i * 2] = (byte) (btemp > 9 ? btemp + 0x61 - 10 : btemp + 0x30);
            btemp = (byte) (bytes[i] & 0x0f);
            temp[i * 2 + 1] = (byte) (btemp > 9 ? btemp + 0x61 -10 : btemp + 0x30);
        }
        return new String(temp);
    }

    /**
     * @功能: 10进制串转为BCD码
     * @参数: 10进制串
     * @结果: BCD码
     */


    /**
     * md5
     *
     * @param str
     * @return
     */
    public static String md5(String str) {
        StringBuilder StringBuilder = new StringBuilder();
        int i = new Double(Math.random() * 10).intValue();
        System.out.println(str + i + "str+i");
        String s = DigestUtils.md5Hex(str + i);
        StringBuilder append = StringBuilder.append(s.substring(0, 8) + s.substring(24, 32));
        System.out.println(append);
        return append.toString();
    }


    /**
     * 主方法测试
     *
     * @param args
     */
    /*public static void main(String[] args) throws Exception {
        String encrypt = encrypt("50");
        System.out.println("加密之后：" + encrypt);
        String decrypt = decrypt(encrypt);
        System.out.println("解密之后：" + decrypt);
    }*/
}
